/**
 * @file test.cc
 * @author zziywang (zziywang@163.com)
 * @brief { life is too short to learn cpp! }
 * @version 1.0
 * @date 2022-05-08
 *
 * @copyright Copyright (c) 2022
 *
 */

#include "ThreadPool.hh"
#include <iostream>
#include <memory>
#include <unistd.h>
using namespace std;
using namespace snow;

void run1()
{
    cout << tls::threadName << " is running..." << endl
         << "run1()" << endl;
}

class MyTask
{
public:
    void run2()
    {
        cout << tls::threadName << " is running..." << endl
             << "Task::run2()" << endl;
    }

    static void run3()
    {
        cout << tls::threadName << " is running..." << endl
             << "Task::run3()" << endl;
    }
};

void test_thread()
{
    // unique_ptr<Thread> thread(new Thread(run1));
    // unique_ptr<Thread> thread(new Thread(std::bind(&MyTask::run2, MyTask())));
    unique_ptr<Thread> thread(new Thread(MyTask::run3));

    thread->start();
    thread->join();
}

class Producer
{
public:
    void run(TaskQue &taskque)
    {
        int cnt = 20;
        int taskNum = 1;
        while (cnt--) {
            taskque.push(std::bind(&MyTask::run2, MyTask()));
            cout << "线程" << tls::threadName
                 << "添加了第" << taskNum++ << "个任务" << endl;
        }
    }
};

class Consumer
{
public:
    void run(TaskQue &taskque)
    {
        int cnt = 20;
        int taskNum = 1;
        while (cnt--) {
            ::sleep(1); // 先让生产者放任务
            ElemType task = taskque.pop();
            cout << "线程" << tls::threadName
                 << "取走了第" << taskNum++ << "个任务" << endl;
            task(); // 消费者做任务
        }
    }
};

void test_pc() // Producer and Comsumer
{
    TaskQue taskque(10);
    unique_ptr<Thread> producer(new Thread(
        std::bind(&Producer::run, Producer(), std::ref(taskque)), "生产者"));
    unique_ptr<Thread> consumer(new Thread(
        std::bind(&Consumer::run, Consumer(), std::ref(taskque)), "消费者"));
    producer->start();
    consumer->start();
    producer->join();
    consumer->join();
}

void test_threadpool()
{
    ThreadPool tp(4, 10);
    tp.start();

    int cnt = 20;
    while (cnt--) {
        tp.addTask(std::bind(&MyTask::run2, MyTask()));
    }
    tp.stop();
}

int main()
{
    // test_thread();
    // test_pc();
    test_threadpool();
    return 0;
}